package com.hyyt.shopjsp.wxmg.util;

import com.hyyt.shopjsp.util.common.StringStaticKey;
import com.hyyt.shopjsp.util.redis.util.RedisDataReadUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.tuckey.web.filters.urlrewrite.utils.Log;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 微信基础工具类
 */
public class WxBasicUtil {
	/**
	 * 日志
	 */
	public static Log logger = Log.getLog(WxBasicUtil.class);

	/**
	 * 获取微信公众号二维码图片地址
	 *
	 */
	public static String getQRCodeImageUrl(String ticket) {
        String qrCodeURL = null;
        qrCodeURL = WxStaticKeyUtil.WX_SHOW_QRCODE_TICKET_URL + ticket;
        return qrCodeURL;
	}

	/**
	 * 获取微信公众号二维码图片文件并且保存至本地
	 *
	 */
	public static void getQRCodeSaveImage(String access_token) {
		StringBuffer bufferRes = new StringBuffer();
		try {
			String qrCodeURL = WxStaticKeyUtil.WX_SHOW_QRCODE_TICKET_URL + URLEncoder.encode(access_token,"UTF-8");
			URL realUrl = new URL(qrCodeURL);
			HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
            // 处理 链接工具类
            conn = httpURLConnectionHandle(conn);
			// 获取URLConnection对象对应的输出流
			InputStream in = conn.getInputStream();
            // 将二进制流转换成图片，获取的微信的二维码图片
			inputStreamToImage(in);
		} catch (Exception e) {
			logger.error(e);
		}
	}

	/**
	 * 获取微信的凭据
	 * 创建二维码ticket：
		 每次创建二维码ticket需要提供一个开发者自行设定的参数（scene_id），分别介绍临时二维码和永久二维码的创建二维码ticket过程。
		 1、临时二维码请求说明
			 http请求方式: POST
			 URL: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKENPOST数据格式：json
			 POST数据例子：{"expire_seconds": 604800, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": 123}}}
			 或者也可以使用以下POST数据创建字符串形式的二维码参数：
			    {"expire_seconds": 604800, "action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str": "test"}}}
	 	 2、永久二维码请求说明
			 http请求方式: POST
			 URL: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKENPOST数据格式：json
			 POST数据例子：{"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_id": 123}}}
			 或者也可以使用以下POST数据创建字符串形式的二维码参数：
			    {"action_name": "QR_LIMIT_STR_SCENE", "action_info": {"scene": {"scene_str": "test"}}}
	 	 3、参数说明
			 expire_seconds	该二维码有效时间，以秒为单位。 最大不超过2592000（即30天），此字段如果不填，则默认有效期为30秒。
			 action_name	二维码类型，QR_SCENE为临时的整型参数值，QR_STR_SCENE为临时的字符串参数值，QR_LIMIT_SCENE为永久的整型参数值，QR_LIMIT_STR_SCENE为永久的字符串参数值
			 action_info	二维码详细信息
			 scene_id	场景值ID，临时二维码时为32位非0整型，永久二维码时最大值为100000（目前参数只支持1--100000）
			 scene_str	场景值ID（字符串形式的ID），字符串类型，长度限制为1到64
         4、返回说明
             正确的Json返回结果:
             {"ticket":"xxx","expire_seconds":60,"url":"http:\/\/weixin.qq.com\/q\/kZgfwMTm72WWPkovabbI"}
             返回参数说明：
                 ticket	获取的二维码ticket，凭借此ticket可以在有效时间内换取二维码。
                 expire_seconds	该二维码有效时间，以秒为单位。 最大不超过2592000（即30天）。
                 url	二维码图片解析后的地址，开发者可根据该地址自行生成需要的二维码图片
         5、通过ticket换取二维码
             获取二维码ticket后，开发者可用ticket换取二维码图片。请注意，本接口无须登录态即可调用。
             请求说明
             HTTP GET请求（请使用https协议）https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET提醒：TICKET记得进行UrlEncode
             返回说明
             ticket正确情况下，http 返回码是200，是一张图片，可以直接展示或者下载。
             HTTP头（示例）如下：
                 Accept-Ranges:bytes
                 Cache-control:max-age=604800
                 Connection:keep-alive
                 Content-Length:28026
                 Content-Type:image/jpg
                 Date:Wed, 16 Oct 2013 06:37:10 GMT
                 Expires:Wed, 23 Oct 2013 14:37:10 +0800
                 Server:nginx/1.4.1
             错误情况下（如ticket非法）返回HTTP错误码404。
	 *
	 * @return String
	 */
	public static String getTicket(String access_token,String customerId,int ticketType) {
		Map<String, String> jsonMap = new HashMap<String, String>();
		StringBuffer bufferRes = new StringBuffer();
		// 获取access_token
		String postCode = null;
		switch (ticketType) {
			case 1://临时二维码，expire_seconds，该二维码有效时间，以秒为单位。 最大不超过2592000（即30天），此字段如果不填，则默认有效期为30秒。
				postCode = "{\"expire_seconds\": 2592000,\"action_name\": \"QR_SCENE\", \"action_info\": {\"scene\": {\"scene_id\": "+customerId+"}}}";
				break;
			case 2://永久二维码
				postCode = "{\"action_name\": \"QR_LIMIT_SCENE\", \"action_info\": {\"scene\": {\"scene_id\": "+customerId+"}}}";
				break;
		}
		try {
			String ticketURL = WxStaticKeyUtil.WX_QRCODE_CREATE_URL + access_token;
			URL realUrl = new URL(ticketURL);
			HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
            // 处理 链接工具类
            conn = httpURLConnectionHandle(conn);
			// 获取URLConnection对象对应的输出流
			OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
			// 发送请求参数
			out.write(postCode);
			out.flush();
			out.close();

			// 获取URLConnection对象对应的输出流
			InputStream in = conn.getInputStream();
			BufferedReader read = new BufferedReader(new InputStreamReader(in, "UTF-8"));
			String valueString = null;
			while ((valueString = read.readLine()) != null) {
				bufferRes.append(valueString);
			}
			in.close();
			if (conn != null) {
				conn.disconnect();
			}
		} catch (Exception e) {
			logger.error(e);
		}
		// 将json字符串转换成map对象
		jsonMap = parseJsonStringToMap(bufferRes.toString());
		return jsonMap.get("ticket");
	}

	/**
	 * 获取微信的凭据
	 *
	 * @return String
	 */
	public static String getTicket(String access_token) {
		Map<String, String> jsonMap = new HashMap<String, String>();
		StringBuffer bufferRes = new StringBuffer();
		// 获取access_token
		String postCode = "{\"action_name\": \"QR_LIMIT_SCENE\", \"action_info\": {\"scene\": {\"scene_id\": 123}}}";
		try {
			String ticketURL = WxStaticKeyUtil.WX_QRCODE_CREATE_URL + access_token;
			URL realUrl = new URL(ticketURL);
			HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
            // 处理 链接工具类
            conn = httpURLConnectionHandle(conn);
			// 获取URLConnection对象对应的输出流
			OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
			// 发送请求参数
			out.write(postCode);
			out.flush();
			out.close();

			// 获取URLConnection对象对应的输出流
			InputStream in = conn.getInputStream();
			BufferedReader read = new BufferedReader(new InputStreamReader(in, "UTF-8"));
			String valueString = null;
			while ((valueString = read.readLine()) != null) {
				bufferRes.append(valueString);
			}
			in.close();
			if (conn != null) {
				conn.disconnect();
			}
		} catch (Exception e) {
			logger.error(e);
		}
		jsonMap = parseJsonStringToMap(bufferRes.toString());
		return jsonMap.get("ticket");
	}

	/**
	 * 获取微信的AccessToken
	 *
	 * @return String 
	 */
	public final static String getAccessToken(String appId, String appSecret) {

		StringBuffer bufferRes = new StringBuffer();
		try {
			String tokenURL = WxStaticKeyUtil.WX_TOKEN_GRANT_TYPE_URL + appId + "&secret=" + appSecret;
			URL realUrl = new URL(tokenURL);
			HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
			// 处理 链接工具类
			conn = httpURLConnectionHandle(conn);
			// 获取URLConnection对象对应的输出流
			InputStream in = conn.getInputStream();
			BufferedReader read = new BufferedReader(new InputStreamReader(in, "UTF-8"));
			String valueString = null;
			while ((valueString = read.readLine()) != null) {
				bufferRes.append(valueString);
			}
			in.close();
			if (conn != null) {
				// 关闭连接
				conn.disconnect();
			}
		} catch (Exception e) {
			logger.error(e);
		}
		Map<String, String> accessTokenMap = parseJsonStringToMap(bufferRes.toString());
		String access_token = accessTokenMap.get("access_token");
		return access_token;
	}

	/**
	 * 获取微信授权的 AccessToken
	 *
	 * @return String 
	 */
	public final static Map<String, String> getOAuthAccessTokenMap(String appId, String appSecret,String code) {

		StringBuffer bufferRes = new StringBuffer();
		try {
			String tokenURL = WxStaticKeyUtil.WX_SNS_OAUTH_APPID_URL +appId+"&secret="+appSecret+"&code="+code;
			URL realUrl = new URL(tokenURL);
			HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
			// 处理 链接工具类
			conn = httpURLConnectionHandle(conn);
			// 获取URLConnection对象对应的输出流
			InputStream in = conn.getInputStream();
			BufferedReader read = new BufferedReader(new InputStreamReader(in, "UTF-8"));
			String valueString = null;
			while ((valueString = read.readLine()) != null) {
				bufferRes.append(valueString);
			}
			in.close();
			if (conn != null) {
				// 关闭连接
				conn.disconnect();
			}
		} catch (Exception e) {
			logger.error(e);
		}
		Map<String, String> accessTokenMap = parseJsonStringToMap(bufferRes.toString());
		return accessTokenMap;
	}

	/**
	 * 平台客服发送消息给粉丝
	 * 注意图文消息：发送图文消息(点击跳转到外链)图文消息条数限制在8条以内，注意，如果图文数超过8，则将会无响应。
	 *
	 * @param 1发送文本消息text 2 发送图片消息image 3 发送语音消息voice 4 发送视频消息video 5 发送音乐消息music 6 发送图文消息news
	 *
	 */
	public static String sendMessage(String access_token,  String json){
		String url = WxStaticKeyUtil.WX_MESSAGE_CUSTOM_SEND_URL + access_token;
		CloseableHttpClient client = HttpClients.createDefault();
		HttpPost post = new HttpPost(url);
		try {
			//json = new String(json.getBytes(), "iso8859-1");
			json = new String(json.getBytes("utf-8"), "iso8859-1");
			StringEntity stringEntity = new StringEntity(json);
			stringEntity.setContentEncoding("iso8859-1");
			//stringEntity.setContentType("application/json");
			stringEntity.setContentType("application/json; encoding=iso8859-1");
			post.setEntity(stringEntity);
			HttpResponse res = client.execute(post);
			if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				HttpEntity entity = res.getEntity();
                String strJson = EntityUtils.toString(entity, "utf-8");
				return strJson;
			}
        } catch (Exception e) {
			logger.error(e);
			//throw new RuntimeException(e);
		}
		return null;
	}

    /**
     * 将二进制流转换成图片，获取的微信的二维码图片
     *
     * @return String
     */
    private static void inputStreamToImage(InputStream in){
        try {
            // 将字符串转换成二进制，用于显示图片
            // 将上面生成的图片格式字符串 imgStr，还原成图片显示
            //byte[] imgByte = hex2byte(imgStr);
            //InputStream in = new ByteArrayInputStream(imgByte);
            File file = new File(RedisDataReadUtil.getSysConfig(StringStaticKey.FILE_UPLOAD_ROOT)+"/"+RedisDataReadUtil.getSysConfig(StringStaticKey.FILE_SYS_WX)+"/"+RedisDataReadUtil.getSysConfig("image_QRCode")+"/"+StringStaticKey.FILE_WX_SHOPJSP_PUBLICNO_QRCODE);//可以是任何图片格式.jpg,.png等
            File file_temp = new File(RedisDataReadUtil.getSysConfig(StringStaticKey.FILE_UPLOAD_ROOT)+"/"+RedisDataReadUtil.getSysConfig(StringStaticKey.FILE_SYS_WX)+"/"+RedisDataReadUtil.getSysConfig("image_QRCode"));//可以是任何图片格式.jpg,.png等
            if (!file_temp.exists()) {
                file_temp.mkdirs();
            }
            FileOutputStream fos=new FileOutputStream(file);
            byte[] b = new byte[1024];
            int nRead = 0;
            while ((nRead = in.read(b)) != -1) {
                fos.write(b, 0, nRead);
            }
            fos.flush();
            fos.close();
            in.close();
        } catch (Exception e) {
            logger.error(e);
        }
    }

    /**
     * 将json字符串转换成map对象
     *
     * @return Map
     */
    public static Map<String, String> parseJsonStringToMap(String jsonString) {
        JSONArray arry = JSONArray.fromObject("[" + jsonString + "]");
        Map<String, String> jsonMap = new HashMap<String, String>();
        if(arry!=null){
            for (int i = 0; i < arry.size(); i++) {
                JSONObject jsonObject = arry.getJSONObject(i);
                for (Iterator<?> iter = jsonObject.keys(); iter.hasNext();) {
                    String key = (String) iter.next();
                    String value = jsonObject.get(key).toString();
                    jsonMap.put(key, value);
                }
            }
        }
        return jsonMap;
    }

	/**
	 * 处理 链接工具类
	 * @param conn 链接参数
	 */
	private static HttpURLConnection httpURLConnectionHandle(HttpURLConnection conn) throws IOException {
		// 连接超时
		conn.setConnectTimeout(25000);
		// 读取超时 --服务器响应比较慢，增大时间
		conn.setReadTimeout(25000);
		HttpURLConnection.setFollowRedirects(true);
		// 请求方式
		conn.setRequestMethod("GET");
		conn.setDoOutput(true);
		conn.setDoInput(true);
		conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0");
		conn.setRequestProperty("Referer", WxStaticKeyUtil.WX_API_URL);
		conn.connect();
		return conn;
	}

}
